using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace ShipkaDefenders.Gameplay
{
    public class Ally : Entity
    {
        public override Vector2 Pos()
        {
            return g.Engine.Sce(g.Engine.Map.Banners[Cue]) + OriginVect();
        }
        public override SelectionState Tap(Vector2 p)
        {
            p = g.Engine.Abs(p);
            Selected = Rend().Intersects(new Rectangle((int)p.X, (int)p.Y, 1, 1));
            if (!Selected && State == EState.Banner_Anim) SetState(EState.Banner);
            return (Selected ? (State == EState.Banner_Anim ? SelectionState.Confirm : (State == EState.Banner ? SelectionState.Banner : SelectionState.Unit)) : SelectionState.None);
        }
        public override void Die()
        {
            LastClass = TextureGroup;
            SetState(EState.Dead);
            SetSprite();
        }
        public void UpdateFight(List<Enemy> le)
        {
            if ((State == EState.Idle || State == EState.Fight) && g.Engine.Status != GameStatus.Paused)
            {
                int FightCount = 0;
                foreach (Enemy e in le)
                {
                    if (Range.Intersects(e, Stats.FightOnY))
                    {
                        FightCount++;
                        e.UnderAttack = true;
                        Flip = e.PosFight().X < PosFight().X;
                        if (e.Stats.DoDamage(Stats.Damage * g.Engine.GameSpeed()))
                        {
                            e.Die();
                        }
                        if (FightCount == Stats.MaxFight)
                            break;
                    }
                    else e.UnderAttack = false;
                }
                SetState(FightCount > 0 ? EState.Fight : EState.Idle);
                SetSprite();
            }
        }
        public bool Selected = false;
        protected Dictionary<string, Vector2> ranges;
        private string LastClass;
        public Ally(AnaLogic game, int cue)
        {
            g = game;
            TextureGroup = string.Empty;
            SetState(EState.Banner);
            Cue = cue;
            Origin = new Vector2(-0.5f, -0.8f);
            SetSprite("banner");
            ranges = new Dictionary<string, Vector2>();
            ranges.Add("russian", new Vector2(0, 70));
            ranges.Add("russian_sniper", new Vector2(80, 350));
        }
        public void Update(TimeSpan e, TimeSpan E)
        {
            if (State.ToString().Contains("Banner"))
                SetSprite(State.ToString().ToLower());
            Sprite.Update(E);
            if (Range != null) Range.Update(this);
            if (State.Equals(EState.Dead))
            {
                Vector2 ts = new Vector2((float)(e - StateStart).TotalSeconds, (float)Stats.RessurrectionTime);
                Stats.Health = new Vector2(((ts.X / ts.Y) * Stats.Health.Y), Stats.Health.Y);
                if (ts.X > ts.Y)
                {   // oh, praise jesus - the soldier's ressurected!
                    Build(LastClass);
                }
            }
        }
        public override void Build(string ClassName)
        {
            TextureGroup = ClassName;
            SetState(EState.Idle);
            Origin = new Vector2(-0.5f, -0.95f);
            Stats = new Gameplay.Stats(100, (ClassName.Equals("russian_sniper")), 1, 1.0f, 5);
            Range = AutoRange(ClassName);
            SetSprite();
        }
        public void DrawSelf()
        {
            if (State.Equals(EState.Banner))
            {
                g.Engine.Drw("banner", Pos(), Convert.ToInt32(Selected));
            }
            else
            {
                Sprite.Draw(g.Engine, Pos(), Flip);
                if (State == EState.Idle || State == EState.Fight || State == EState.Dead) DrawHealth();
                if (Selected)
                {
                    if (State == EState.Idle || State == EState.Fight || State == EState.Dead)
                    {
                        Range.DrawSelf(g);
                    }
                    else if (State == EState.Banner_Anim)
                    {
                        Range r = AutoRange();
                        Vector2 displacement = new Vector2(0, 25);
                        r.Move(r.Inner.Center - displacement);
                        r.DrawSelf(g);
                    }
                }
            }
        }
        protected Range AutoRange() { return AutoRange(g.Engine.Hud.SelectedUnitType); }
        protected Range AutoRange(string i)
        {
            Vector2 rv = ranges[i];
            return new Range(g.Engine, this, rv.X, rv.Y);
        }
        protected Range AutoRange(int i)
        {
            Vector2 rv = ranges.ElementAt(i - 1).Value;
            return new Range(g.Engine, this, rv.X, rv.Y);
        }
    }
    public class Enemy : Entity
    {
        public override Vector2 Pos()
        {
            return Position - OriginVect();
        }
        public override void Die()
        {
            g.Engine.DelEnemies.Add(Index);
        }
        protected void Pass()
        {
            Die();
            g.Engine.Pass--;
        }
        public void UpdateFight(List<Ally> la)
        {
            if ((State == EState.Walk || State == EState.Fight) && g.Engine.Status != GameStatus.Paused)
            {
                bool InCombat = false;
                foreach (Ally a in la)
                {
                    if (Range.Intersects(a, Stats.FightOnY))
                    {
                        InCombat = true;
                        Flip = a.PosFight().X < PosFight().X;
                        if (a.Stats.DoDamage(Stats.Damage * g.Engine.GameSpeed()))
                        {
                            a.Die();
                        }
                        break;
                    }
                }
                EState e = this.State;
                SetState(InCombat ? EState.Fight : EState.Walk);
                if (InCombat) motiontime += (float)g.Engine.UpdateTime(g.UpdateTime).Milliseconds;
                SetSprite();
            }
        }
        protected MotionPath mp;
        protected float motiontime;
        public Enemy(AnaLogic game)
        {
            g = game;
            Build((new Random().Next(2).Equals(0) ? "turk" : "turk_scout"));
            SetState(EState.Walk);
            Sprite = new AnimatedSprite(g, this);
            mp = new MotionPath(g.Engine);
            motiontime = (float)(g.Engine.GetTime() - g.ScreenTime).TotalMilliseconds;
            g.Engine.Map.LoadCurveKeys(mp);
        }
        public override void Build(string ClassName)
        {
            TextureGroup = ClassName;
            switch (ClassName)
            {
                case "turk":
                    Stats = new Stats(100, false, 1, 0.5f, 0);
                    Origin = new Vector2(0.5f, 0.95f);
                    SpriteInfo = new Vector3(100);
                    break;
                case "turk_scout":
                    Stats = new Stats(100, false, 1, 0.5f, 0);
                    Origin = new Vector2(0.5f, 0.95f);
                    SpriteInfo = new Vector3(84, 100, 126);
                    break;
            }
        }
        string stt = string.Empty;
        public void Update(TimeSpan e, TimeSpan E)
        {
            float olx = Position.X;
            float mt = (float)(e.TotalMilliseconds - motiontime);
            if (State.Equals(EState.Walk) && g.Engine.Enemies.Count > (Index + 1))
                if (Math.Abs(g.Engine.Enemies[Index + 1].Rend().X - Rend().X) < 40)
                {
                    motiontime += (float)g.Engine.UpdateTime(TimeSpan.FromMilliseconds(g.Engine.Rand.Next(10, 42))).TotalMilliseconds;
                }
            Position = mp.Evaluate(mt);
            
            if (Position == Vector2.Zero) Pass();
            else
            {
                Flip = (olx > Position.X);
                Sprite.Update(E);
            }
            Range = new Range(g.Engine, this, 0, 40);
        }
        public void DrawSelf()
        {
            Sprite.Draw(g.Engine, Pos(), Flip);
            g.WriteString("Segoe", 16, stt, (Position + g.Engine.Scroll - OriginVect()), Color.Yellow);
            //Range.DrawSelf(g, 0.0f);
            DrawHealth();
        }
    }
    public class WaveManager
    {
        protected GameEngine g;
        public WaveManager(GameEngine game)
        {
            g = game;
        }
        private int updates;
        public void Update()
        {
            TimeSpan t = g.GetGameplayTime();
            if (updates % 60 == 0)
            {
                Enemy e = new Enemy(g.GetGameClass());
                g.Enemies.Add(e);
            }
            updates += (g.Status == GameStatus.FastForward ? 2 : (g.Status == GameStatus.Running ? 1 : 0));
            if (updates > 666) updates = 0;
        }
    }
    public class PlayerData
    {
        public string TextureGroup { get; set; }
        public EState DefaultState { get; set; }
        public float Health { get; set; }
        public bool FightVertical { get; set; }
        public int MaxFighting { get; set; }
        public float Damage { get; set; }
        public double RessurectionTime { get; set; }
        public Vector2 Origin { get; set; }
        public float TextureSize { get; set; }
    }
}
